package com.nage.components.display;

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
import javax.microedition.khronos.opengles.GL11Ext;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import android.util.Log;

import com.nage.components.Component;
import com.nage.engine.GameObject;
import com.nage.engine.Main;
import com.nage.graphics.RenderSystem;

public class Sprite extends Component implements Drawable {
	
	private int mTextureName; // name used to refer to the texture that has been loaded into graphics memory.
	private int mResourceId; // resourceId used to get the bitmap from /res file.
	
	public int width, height;
	public float x, y, z;
	private boolean textureLoaded;
	private int[] mCropWorkspace;
	

	public Sprite(GameObject p, int resourceId) {
		super(p);
		type = SPRITE; 
		mResourceId = resourceId;
		mCropWorkspace = new int[4];
		x = parent.getX();
		y = parent.getY();
		RenderSystem.registerDrawable(this);
	}

	@Override
	public void render(GL10 gl) {
	   	if(!textureLoaded) {
    		calcVertices(gl, Main.engine.context);
    	}
        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureName);
        ((GL11Ext) gl).glDrawTexfOES(x, y, z, width, height); // uses Draw Texture extension. What devices is this available on?

	}

	/**
	 * In this case, calcVertices doesn't actually calcVertices... this method should be called
	 * once the sprite has been initialised, but before it is asked to render. We can use this
	 * oppurtunity to load the texture into graphics memory and set mTextureName so that when
	 * it renders it will work.
	 */
	@Override
	public void calcVertices(GL10 gl, Context c) {
		Log.d("Sprite", "calcVertices called...");
		if(!textureLoaded) {
			mTextureName = loadBitmap(c, gl, mResourceId);
			textureLoaded = true;
		}
	}

	@Override
	public void update(long delta) {
		x = parent.getX();
		y = parent.getY();

	}
	
    /** 
     * Loads a bitmap into OpenGL and sets up the common parameters for 
     * 2D texture maps. 
     */
    protected int loadBitmap(Context context, GL10 gl, int resourceId) {
 
        int textureName = -1;
        if (context != null && gl != null) {
            gl.glGenTextures(1, RenderSystem.mTextureNames, 0);
            Log.d("Sprite", "Loading resource id "+resourceId);

            textureName = RenderSystem.mTextureNames[0];
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textureName);

            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);

            gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE);

            InputStream is = context.getResources().openRawResource(resourceId);
            Bitmap bitmap;
            try {
                bitmap = BitmapFactory.decodeStream(is, null, RenderSystem.sBitmapOptions);
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                    // Ignore.
                }
            }

            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

            mCropWorkspace[0] = 0;
            mCropWorkspace[1] = bitmap.getHeight();
            mCropWorkspace[2] = bitmap.getWidth();
            mCropWorkspace[3] = -bitmap.getHeight();
            
            bitmap.recycle();

            ((GL11) gl).glTexParameteriv(GL10.GL_TEXTURE_2D, 
                    GL11Ext.GL_TEXTURE_CROP_RECT_OES, mCropWorkspace, 0);

            
            int error = gl.glGetError();
            if (error != GL10.GL_NO_ERROR) {
                Log.e("Sprite", "Texture Load GLError: " + error);
            }
        
        }

        Log.d("Sprite", "Texture loaded. Name = "+textureName);
        return textureName;
    }
	
	public void setWidth(String w) {
		if(w!=null) {
			width = Integer.parseInt(w);
		}
	}
	
	public void setHeight(String h) {
		if(h!=null) {
			height = Integer.parseInt(h);
		}
	}

}
